{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-----------------------------------------------------------------------------
--
-- Module      :  Control.Monad.Counter
-- Copyright   :  Mikhail Belyaev
-- License     :  GPL (Just (Version {versionBranch = [3], versionTags = []}))
--
-- Maintainer  :
-- Stability   :
-- Portability :
--
-- |
--
-----------------------------------------------------------------------------

module Control.Monad.Counter where

import Control.Monad.State.Lazy (execStateT, StateT(..))
import Control.Monad (MonadPlus)
import Control.Monad.Fix (MonadFix)
import Control.Monad.State.Class (MonadState(..))


newtype CounterT m a = StToCount { countToSt:: StateT Integer m a} deriving (Monad,MonadPlus,MonadFix)

incCnt :: (Monad m) => CounterT m ()
incCnt = addCnt 1

addCnt :: (Monad m) => Integer -> CounterT m ()
addCnt a = StToCount $ do s <- get
                          put $ s+a
                          return ()

counted :: (Monad m) => CounterT m Integer
counted = StToCount $ do{ s <- get; return s }

startCount :: (Monad m) => CounterT m () -> m Integer
startCount = startCountFrom 0

startCountFrom :: (Monad m) => Integer -> CounterT m () -> m Integer
startCountFrom val cnt = execStateT (countToSt cnt) val
